package com.whosly.mysql.protocol.jdbc;

import com.whosly.mysql.protocol.TransactionIsolation;
import com.whosly.mysql.protocol.config.MySQLProtocolConfig;
import com.whosly.mysql.protocol.constant.NettyDefaultConstants;
import com.whosly.mysql.protocol.datatype.DataType;

import java.time.ZoneId;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * @author 风杨
 * @date 2023年06月25日 下午9:21
 * @see <a href="yueny09@163.com">mailTo: yueny09@163.com</a>
 */
public interface VariableDefinition {

    /**
     * GMT+08:00
     */
    public static final TimeZone GMT_8_TIMEZONE = TimeZone.getTimeZone(ZoneId.of("+8"));
    /**
     * 本地时区。 如 GMT+08:00
     */
    public static final TimeZone LOCAL_TIMEZONE = TimeZone.getTimeZone(ZoneId.of(timeZoneId(
            TimeZone.getDefault())));

    static String timeZoneId(TimeZone zone) {
        int offset = zone.getRawOffset();
        if (offset >= 0) {
            return ("+" + offset / 3600 / 1000);
        } else {
            return ("" + offset / 3600 / 1000);
        }
    }

    enum VARIABLES {
        tx_isolation("tx_isolation", TransactionIsolation.READ_UNCOMMITTED.getTransIsolationNameToValue()),

        /**
         * cmd
         */
        auto_increment_increment("auto_increment_increment","1", DataType.LONG),
        auto_increment_offset("auto_increment_offset","1"),
        autocommit("autocommit", "ON"),
        automatic_sp_privileges("automatic_sp_privileges", "ON"),
        back_log("back_log", "50"),
        basedir("basedir", "/home/mysql/mysql-5.1.22-rc-linux-i686-glibc23/"),
        big_tables("big_tables", "OFF"),
        binlog_cache_size("binlog_cache_size", "32768"),
        binlog_format("binlog_format", "MIXED"),
        bulk_insert_buffer_size("bulk_insert_buffer_size", "8388608"),
        character_set_client("character_set_client", "utf8"),
        character_set_connection("character_set_connection", "utf8"),
        character_set_database("character_set_database", "utf8"),
        character_set_filesystem("character_set_filesystem", "binary"),
        character_set_results("character_set_results", "utf8"),
        character_set_server("character_set_server", "utf8"),
        character_set_system("character_set_system", "utf8"),
        collation_connection("collation_connection", "utf8_general_ci"),
        collation_database("collation_database", "utf8_general_ci"),
        collation_server("collation_server", "utf8_general_ci"),
        completion_type("completion_type", "0"),
        concurrent_insert("concurrent_insert", "1"),
        /**
         * netty连接超时时间
         */
        connect_timeout("connect_timeout", String.valueOf(TimeUnit.MILLISECONDS.toSeconds(
                NettyDefaultConstants.defaultNettyConnectTimeoutMs))),
        date_format("date_format", "%Y-%m-%d"),
        datetime_format("datetime_format", "%Y-%m-%d %H:%i:%s"),
        default_week_format("default_week_format", "0"),
        delay_key_write("delay_key_write", "ON"),
        delayed_insert_limit("delayed_insert_limit", "100"),
        delayed_insert_timeout("delayed_insert_timeout", "300"),
        delayed_queue_size("delayed_queue_size", "1000"),
        div_precision_increment("div_precision_increment", "4"),
        engine_condition_pushdown("engine_condition_pushdown", "ON"),
        error_count("error_count", "0"),
        event_scheduler("event_scheduler", "OFF"),
        expire_logs_days("expire_logs_days", "0"),
        flush("flush", "OFF"),
        flush_time("flush_time", "0"),
        foreign_key_checks("foreign_key_checks", "ON"),
        ft_boolean_syntax("ft_boolean_syntax", "+ -&gt;&lt;()~*:&quot;&quot;&amp;|"),
        ft_max_word_len("ft_max_word_len", "84"),
        ft_min_word_len("ft_min_word_len", "4"),
        ft_query_expansion_limit("ft_query_expansion_limit", "20"),
        ft_stopword_file("ft_stopword_file", "(built-in)"),
        general_log("general_log","OFF"),
        group_concat_max_len("group_concat_max_len","1024"),
        have_compress("have_compress","YES"),
        have_crypt("have_crypt","YES"),
        have_csv("have_csv","YES"),
        have_dynamic_loading("have_dynamic_loading","YES"),
        have_geometry("have_geometry","YES"),
        have_innodb("have_innodb","YES"),
        have_ndbcluster("have_ndbcluster","NO"),
        have_openssl("have_openssl","DISABLED"),
        have_partitioning("have_partitioning","YES"),
        have_query_cache("have_query_cache","YES"),
        have_rtree_keys("have_rtree_keys","YES"),
        have_ssl("have_ssl","DISABLED"),
        have_symlink("have_symlink","YES"),
        hostname("hostname","community-dev3"),
        identity("identity","0"),
        init_connect("init_connect",""),
        init_file("init_file",""),
        init_slave("init_slave",""),
        innodb_additional_mem_pool_size("innodb_additional_mem_pool_size","1048576"),
        innodb_autoextend_increment("innodb_autoextend_increment","8"),
        innodb_autoinc_lock_mode("innodb_autoinc_lock_mode","1"),
        innodb_buffer_pool_size("innodb_buffer_pool_size","8388608"),
        innodb_checksums("innodb_checksums","ON"),
        innodb_commit_concurrency("innodb_commit_concurrency","0"),
        innodb_concurrency_tickets("innodb_concurrency_tickets","500"),
        innodb_data_file_path("innodb_data_file_path","ibdata1:10M:autoextend"),
        innodb_data_home_dir("innodb_data_home_dir",""),
        innodb_doublewrite("innodb_doublewrite","ON"),
        innodb_fast_shutdown("innodb_fast_shutdown","1"),
        innodb_file_io_threads("innodb_file_io_threads","4"),
        innodb_file_per_table("innodb_file_per_table","OFF"),
        innodb_flush_log_at_trx_commit("innodb_flush_log_at_trx_commit","1"),
        innodb_flush_method("innodb_flush_method",""),
        innodb_force_recovery("innodb_force_recovery","0"),
        innodb_lock_wait_timeout("innodb_lock_wait_timeout","50"),
        innodb_locks_unsafe_for_binlog("innodb_locks_unsafe_for_binlog","OFF"),
        innodb_log_buffer_size("innodb_log_buffer_size","1048576"),
        innodb_log_file_size("innodb_log_file_size","5242880"),
        innodb_log_files_in_group("innodb_log_files_in_group","2"),
        innodb_max_dirty_pages_pct("innodb_max_dirty_pages_pct","90"),
        innodb_max_purge_lag("innodb_max_purge_lag","0"),
        innodb_mirrored_log_groups("innodb_mirrored_log_groups","1"),
        innodb_open_files("innodb_open_files","300"),
        innodb_rollback_on_timeout("innodb_rollback_on_timeout","OFF"),
        innodb_support_xa("innodb_support_xa","ON"),
        innodb_sync_spin_loops("innodb_sync_spin_loops","20"),
        innodb_table_locks("innodb_table_locks","ON"),
        innodb_thread_concurrency("innodb_thread_concurrency","8"),
        innodb_thread_sleep_delay("innodb_thread_sleep_delay","10000"),
        insert_id("insert_id","0"),
        interactive_timeout("interactive_timeout","28800", DataType.LONG),
        join_buffer_size("join_buffer_size","131072"),
        keep_files_on_create("keep_files_on_create","OFF"),
        key_buffer_size("key_buffer_size","402653184"),
        key_cache_age_threshold("key_cache_age_threshold","300"),
        key_cache_block_size("key_cache_block_size","1024"),
        key_cache_division_limit("key_cache_division_limit","100"),
        large_files_support("large_files_support","ON"),
        large_page_size("large_page_size","0"),
        large_pages("large_pages","OFF"),
        last_insert_id("last_insert_id","0"),
        lc_time_names("lc_time_names","en_US"),
        license("license","RushDB"),
        local_infile("local_infile","ON"),
        locked_in_memory("locked_in_memory","OFF"),
        log("log","OFF"),
        log_bin("log_bin","ON"),
        log_bin_trust_function_creators("log_bin_trust_function_creators","ON"),
        log_bin_trust_routine_creators("log_bin_trust_routine_creators","ON"),
        log_error("log_error","/usr/local/mysql/data/community-dev3.err"),
        log_output("log_output","FILE"),
        log_queries_not_using_indexes("log_queries_not_using_indexes","ON"),
        log_slave_updates("log_slave_updates","OFF"),
        log_slow_queries("log_slow_queries", "ON"),
        log_warnings("log_warnings", "1"),
        long_query_time("long_query_time", "1.000000"),
        low_priority_updates("low_priority_updates", "OFF"),
        lower_case_file_system("lower_case_file_system", "OFF"),
        lower_case_table_names("lower_case_table_names", "0", DataType.LONG),
        max_allowed_packet("max_allowed_packet", "33554432", DataType.LONG),
        max_binlog_cache_size("max_binlog_cache_size", "4294967295"),
        max_binlog_size("max_binlog_size", "1073741824"),
        max_connect_errors("max_connect_errors", "10"),
        max_connections("max_connections",
                String.valueOf(MySQLProtocolConfig.defaultMaxConnections),
                ()-> String.valueOf(MySQLProtocolConfig.defaultMaxConnections)),
        /**
         * ANY_USERS 所有用户维度(不包含内置用户)限制的最大连接数
         */
        max_connections_any_users("max_connections_any_users",
                String.valueOf(MySQLProtocolConfig.maxConnectionsAnyUsers),
                ()-> String.valueOf(MySQLProtocolConfig.maxConnectionsAnyUsers)),
        max_delayed_threads("max_delayed_threads", "20"),
        max_error_count("max_error_count", "64"),
        max_heap_table_size("max_heap_table_size", "16777216"),
        max_insert_delayed_threads("max_insert_delayed_threads", "20"),
        max_join_size("max_join_size", "18446744073709551615"),
        max_length_for_sort_data("max_length_for_sort_data", "1024"),
        max_prepared_stmt_count("max_prepared_stmt_count", "16382"),
        max_relay_log_size("max_relay_log_size", "0"),
        max_seeks_for_key("max_seeks_for_key", "4294967295"),
        max_sort_length("max_sort_length", "1024"),
        max_sp_recursion_depth("max_sp_recursion_depth","0"),
        max_tmp_tables("max_tmp_tables","32"),
        max_user_connections("max_user_connections","0"),
        max_write_lock_count("max_write_lock_count","4294967295"),
        min_examined_row_limit("min_examined_row_limit","0"),
        multi_range_count("multi_range_count","256"),
        myisam_data_pointer_size("myisam_data_pointer_size","6"),
        myisam_max_sort_file_size("myisam_max_sort_file_size","2147483647"),
        myisam_recover_options("myisam_recover_options","OFF"),
        myisam_repair_threads("myisam_repair_threads","1"),
        myisam_sort_buffer_size("myisam_sort_buffer_size","67108864"),
        myisam_stats_method("myisam_stats_method","nulls_unequal"),
        myisam_use_mmap("myisam_use_mmap","OFF"),
        ndb_autoincrement_prefetch_sz("ndb_autoincrement_prefetch_sz","32"),
        ndb_cache_check_time("ndb_cache_check_time","0"),
        ndb_connectstring("ndb_connectstring",""),
        ndb_extra_logging("ndb_extra_logging","0"),
        ndb_force_send("ndb_force_send","ON"),
        ndb_index_stat_cache_entries("ndb_index_stat_cache_entries","32"),
        ndb_index_stat_enable("ndb_index_stat_enable", "OFF"),
        ndb_index_stat_update_freq("ndb_index_stat_update_freq", "20"),
        ndb_report_thresh_binlog_epoch_slip("ndb_report_thresh_binlog_epoch_slip", "3"),
        ndb_report_thresh_binlog_mem_usage("ndb_report_thresh_binlog_mem_usage", "10"),
        ndb_use_copying_alter_table("ndb_use_copying_alter_table", "OFF"),
        ndb_use_exact_count("ndb_use_exact_count", "ON"),
        ndb_use_transactions("ndb_use_transactions", "ON"),
        net_buffer_length("net_buffer_length", "16384", DataType.LONG),
        net_read_timeout("net_read_timeout", "60000"),
        net_retry_count("net_retry_count", "10"),
        net_write_timeout("net_write_timeout", "60000", DataType.LONG),
        _new("new", "OFF"),
        old("old", "OFF"),
        old_alter_table("old_alter_table", "OFF"),
        old_passwords("old_passwords", "OFF"),
        open_files_limit("open_files_limit", "51200"),
        optimizer_prune_level("optimizer_prune_level", "1"),
        optimizer_search_depth("optimizer_search_depth", "62"),
        port("port", String.valueOf(MySQLProtocolConfig.DEFAULT_MYSQL_PROTOCOL_PORT)),
        preload_buffer_size("preload_buffer_size", "32768"),
        protocol_version("protocol_version", String.valueOf(MySQLProtocolConfig.PROTOCOL_VERSION)),
        pseudo_thread_id("pseudo_thread_id", "176577"),
        query_alloc_block_size("query_alloc_block_size", "8192"),
        query_cache_limit("query_cache_limit", "1048576"),
        query_cache_min_res_unit("query_cache_min_res_unit", "4096"),
        query_cache_size("query_cache_size", "0", DataType.LONG),
        query_cache_type("query_cache_type", "OFF"),
        query_cache_wlock_invalidate("query_cache_wlock_invalidate", "OFF"),
        query_prealloc_size("query_prealloc_size", "8192"),
        //        rand_seed1("rand_seed1",""),
//        rand_seed2("rand_seed2",""),
        range_alloc_block_size("range_alloc_block_size", "2048"),
        read_buffer_size("read_buffer_size", "2093056"),
        read_only("read_only", "OFF"),
        read_rnd_buffer_size("read_rnd_buffer_size", "8384512"),
        relay_log_purge("relay_log_purge", "ON"),
        relay_log_space_limit("relay_log_space_limit", "0"),
        rpl_recovery_rank("rpl_recovery_rank", "0"),
        secure_auth("secure_auth", "OFF"),
        secure_file_priv("secure_file_priv", ""),
        server_id("server_id", "1"),
        skip_external_locking("skip_external_locking", "ON"),
        skip_networking("skip_networking", "OFF"),
        skip_show_database("skip_show_database", "OFF"),
        slave_compressed_protocol("slave_compressed_protocol", "OFF"),
        slave_load_tmpdir("slave_load_tmpdir", "/tmp"),
        slave_net_timeout("slave_net_timeout", "3600"),
        slave_skip_errors("slave_skip_errors", "OFF"),
        slave_transaction_retries("slave_transaction_retries", "10"),
        slow_launch_time("slow_launch_time", "2"),
        slow_query_log("slow_query_log", "ON"),
        socket("socket", "/tmp/mysql.sock"),
        sort_buffer_size("sort_buffer_size", "2097144"),
        /**
         * MYSQL  认证超时时间
         */
        mysql_auth_timeout_second("mysql_auth_timeout_second", MySQLProtocolConfig.connectionTimeoutSecond + ""),
        sql_auto_is_null("sql_auto_is_null", "ON"),
        sql_big_selects("sql_big_selects", "ON"),
        sql_big_tables("sql_big_tables", "OFF"),
        sql_buffer_result("sql_buffer_result", "OFF"),
        sql_log_bin("sql_log_bin", "ON"),
        sql_log_off("sql_log_off", "OFF"),
        sql_log_update("sql_log_update", "ON"),
        sql_low_priority_updates("sql_low_priority_updates", "OFF"),
        sql_max_join_size("sql_max_join_size", "18446744073709551615"),
        /**
         * job任务时提交的最大数量
         */
        sql_max_row_job_size("sql_max_row_job_size", String.valueOf(MySQLProtocolConfig.DEFAULT_MAX_ROW_IN_JOB)),
        sql_mode("sql_mode", "PIPES_AS_CONCAT,STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION"),
        sql_notes("sql_notes", "ON"),
        sql_quote_show_create("sql_quote_show_create", "ON"),
        sql_safe_updates("sql_safe_updates", "OFF"),
        sql_select_limit("sql_select_limit", "18446744073709551615"),
        sql_slave_skip_counter("sql_slave_skip_counter", ""),
        sql_warnings("sql_warnings", "OFF"),
        ssl_ca("ssl_ca", ""),
        ssl_capath("ssl_capath", ""),
        ssl_cert("ssl_cert", ""),
        ssl_cipher("ssl_cipher", ""),
        ssl_key("ssl_key", ""),
        storage_engine("storage_engine", "MyISAM"),
        sync_binlog("sync_binlog", "0"),
        sync_frm("sync_frm", "ON"),

        /**
         * 系统时区。 默认不变： Asia/Shanghai
         */
        system_time_zone("system_time_zone", Calendar.getInstance().getTimeZone().getID()),
        /**
         * 用户时区。 默认 GMT+08:00
         */
        time_zone("time_zone", GMT_8_TIMEZONE.getID()),

        time_format("time_format", "%H:%i:%s"),
        timezone("timezone", "+08:00"),
        table_definition_cache("table_definition_cache", "128"),
        table_lock_wait_timeout("table_lock_wait_timeout", "50", DataType.LONG),
        table_open_cache("table_open_cache", "512"),
        table_type("table_type", "MyISAM"),
        thread_cache_size("thread_cache_size", "8"),
        thread_handling("thread_handling", "one-thread-per-connection"),
        thread_stack("thread_stack", "196608"),
        timed_mutexes("timed_mutexes", "OFF"),
        timestamp("timestamp", "1224842449"),
        tmp_table_size("tmp_table_size", "16777216"),
        tmpdir("tmpdir", "/tmp"),
        transaction_alloc_block_size("transaction_alloc_block_size", "8192"),
        transaction_prealloc_size("transaction_prealloc_size", "4096"),
        unique_checks("unique_checks", "ON"),
        updatable_views_with_limit("updatable_views_with_limit", "YES"),
        // todo
//        version("version", MySQLServerInfo.getServerVersion()),
        version_comment("version_comment", "MySQL Community Server (GPL)@RushDB"),
        version_compile_machine("version_compile_machine", "i686"),
        version_compile_os("version_compile_os", "redhat-linux-gnu"),
        wait_timeout("wait_timeout", "28800", DataType.LONG),
        warning_count("warning_count", "0");

        private String name;
        private String val;
        private DataType type;

        // 获取配置值的方法
        private Supplier<String> supplier;

        private VARIABLES(String cmd, String val) {
            this(cmd, val, DataType.STRING);
        }

        private VARIABLES(String cmd, String val, DataType dataType) {
            this.name = cmd;
            this.val = val;
            this.type = dataType;
        }

        private VARIABLES(String cmd, String val, Supplier<String> supplier) {
            this(cmd, val, DataType.STRING);
            this.supplier = supplier;
        }

        public String getName() {
            return name;
        }

        public String getVal() {
            String value = null;
            // 存在配置取值方法时，从配置取值
            if (this.supplier != null) {
                value = supplier.get();
            }
            if (value == null) {
                return val;
            }
            return value;
        }

        public DataType getType() {
            return type;
        }

        /**
         * 是否易变，易变的配置需要重新取值
         * @return true: 值易变
         */
        public boolean isVolatility() {
            return supplier != null;
        }
    }

}
